/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package redis.manage;

/**
 *
 * @author dell
 */
import entity.structure.*;
import entity.support.Area;
import entity.support.Obj;
import conf.XmlUtil;
import entity.support.KeyValue;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
import java.util.Set;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class MRedis extends Redis
{
//functions_____________________________________________________________________  
     //constructor______________________________________________________________
protected MRedis()
{
     
}
     //operators________________________________________________________________
/**
 * get all properties and values of the object,and perse them in a map
 * @param value 
 * @return 
 * @pass
 */
private Map<String,String> getColumns(Object value,Class c1)
{
     HashMap<String,String> map=new HashMap<String,String>();
     Field f2[]=c1.getSuperclass().getDeclaredFields();
     for (Field f21 : f2) 
     {
         try 
         {
             f21.setAccessible(true);
             String key=f21.getName();
             Object v=f21.get(value);
             if(v!=null) map.put(key, v.toString());
         }
         catch(IllegalAccessException | IllegalArgumentException | SecurityException e)
         { 
             e.printStackTrace();
         }
     }
     Field f1[]=c1.getDeclaredFields();
     for (Field f11 : f1) 
     {
         try 
         {
             f11.setAccessible(true);
             String key=f11.getName();
             Object v=f11.get(value);
             if(v!=null)
             {
                 if("area".equals(key))
                 { 
                     Area a=(Area)v;
                     map.put("area_description", a.getDescription());
                     map.put("area_longtitude",""+a.getLongtitude());
                     map.put("area_latitude", ""+a.getLatitude());
                 }
                 else map.put(key, v.toString());
             }
         }
         catch(IllegalAccessException | IllegalArgumentException | SecurityException e)
         {
             e.printStackTrace();
         }
     }
     return map;
}
/**
 * init this MRedis instance by reading a specified xml file accoring
 * to the url.
 * @param url 
 */
@Override
protected void init(String url)
{
     NodeList map=XmlUtil.getNodeList(url, "maps").item(0).getChildNodes();
     List<Class> classes=new LinkedList<Class>();
     List<Integer> targets=new LinkedList<Integer>();
     for(int i=0;i<map.getLength();i++)
     { 
         Node n=map.item(i);
         if(n.getNodeType()==Node.ELEMENT_NODE)
         {
             NodeList m=n.getChildNodes();
             for(int j=0;j<m.getLength();j++)
             {
                 Node k=m.item(j);
                 if(k.getNodeType()==Node.ELEMENT_NODE)
                 {
                     String name=k.getNodeName();
                     String value=k.getFirstChild().getNodeValue();
                     try
                     {                         
                          if("class".equals(name)) classes.add(Class.forName(value));
                          else if("target".equals(name)) targets.add(Integer.valueOf(value));
                     }
                     catch(Exception e)
                     {
                          e.printStackTrace();
                     }
                 }
             }
         }
     }
     Iterator<Class> p1=classes.iterator();
     Iterator<Integer> p2=targets.iterator();
     this.maps=new KeyValue[classes.size()]; 
     for(int i=0;i<this.maps.length;i++)
     {
          Class clazz=p1.next();
          Integer target=p2.next();
          this.maps[i]=new KeyValue<Class,Integer>(clazz,target);
     }
}
         //data management functions____________________________________________
/**
 * give the class of an Obj instance,and return the mapped dbindex
 * @param c
 * @return 
 * @pass
 */
@Override
protected int getDBIndex(Class c) 
{
     int index=-1;
     for (KeyValue<Class, Integer> map : this.maps)
     if (c==map.getKey()) index = map.getValue();
     return index;
}
/**
 * give an instance of Obj,and insert it to Redis
 * @param value
 * @return 
 */
public String insert(Obj value) 
{
     String key=value.getId()+"*"+value.getName();
     Class clazz=value.getClass();
     jedis.select(this.getDBIndex(clazz));
     return jedis.hmset(key, this.getColumns(value,clazz));
}
/**
 * @param clazz the Class of the target 
 * @param key the key words for search
 * @return 
 * @pass
 */
public List<Obj> select(Class clazz,String key) 
{
     List<Obj> list=new LinkedList<Obj>();
     jedis.select(this.getDBIndex(clazz));
     Set<String >keys=jedis.keys(key);
     Iterator<String> p=keys.iterator();
     Constructor con=null;
     try
     {
         con=clazz.getConstructor(java.util.Map.class);
         while(p.hasNext())
         {
             String k=p.next();
             Map<String,String> fields=jedis.hgetAll(k);
             list.add((Obj) con.newInstance(fields));
          }
     }
     catch(Exception e)
     {
          e.printStackTrace();
     }
    
     return list;
}
public static void main(String[] asd)
{
     MRedis a=MRedisPool.getMRedis();
     a.select(Device.class, "*");
}
}